<?php

namespace App\Services;

use App\Exceptions\ApiException;
use App\Models\ArchiveManageVolume;
use App\Models\PartCompany;
use App\Models\PartCompanyClassify;
use App\Models\PhotoClassify;
use App\Models\Project;
use App\Models\ProjectClassify;
use App\Models\RefreshLog;
use Carbon\Carbon;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;

/**
 * 参建单位服务类
 * Class PartCompanyService
 * @package App\Services
 */
class PartCompanyService extends BaseService
{
    /**
     * 添加数据
     *
     * @param $params
     * @return bool
     * @author: lxk
     * @date: 2024/3/20 9:57
     */
    public function saveData($params) : bool
    {
        $title = format_str($params['title']);
        $text  = '添加';
        if (request()->filled('id')) { //更新
            $text = '更新';
            $partCompany = PartCompany::query()->where('id', $params['id'])->first();
            $detail = "数据ID:{$params['id']};把{$partCompany->title}修改为{$title}";
        } else { //新增
            $partCompany = new PartCompany();
            $detail = "数据ID:{$partCompany->id}; {$title}";
        }
        $partCompany->company_id   = company_id();
        $partCompany->project_id   = $params['project_id'];
        $partCompany->type         = $params['type'];
        $partCompany->title        = $title;
        $partCompany->file_date    = format_str($params['file_date']);
        $partCompany->contract_num = format_str($params['contract_num']);
        $partCompany->match_units  = isset($params['match_units']) ? format_str($params['match_units']) : '';
        $partCompany->creator_id   = user_id();

        CommonService::addActionLog("{$text}参建单位", $detail);

        return $partCompany->save();
    }

    /**
     * 获取一条数据信息
     *
     * @param $id
     * @return array
     * @throws ApiException
     * @author: lxk
     * @date: 2024/3/20 9:57
     */
    public function getInfo($id) : array
    {
        $info = PartCompany::query()->where('id', $id)->first();
        if (!empty($info)) {
            return $info->toArray();
        } else {
            throw new ApiException('参见单位不存在~');
        }
    }

    /**
     * 查询项目下的参建单位
     * $type = 1 ：建设单位，可以查看全部
     * $type = 2 ：监理单位，仅可以看自己所在的监理单位和匹配的施工单位
     * $type = 3 ：施工单位，仅可以看自己所在的施工单位
     */
    public function getList($projectId, $searchType, $perPage='')
    {
        $ids = $this->getPartCompanyIds($projectId);

        $thisQuery = PartCompany::query()->whereIn('id', $ids);

        if (!empty($searchType)) { //如果进行了搜索
            $thisQuery->where('type', '=', $searchType);
        }
        $list = $thisQuery
            ->orderBy('type')
            ->orderBy('id') //加一个唯一字段，防止分页丢失数据
            ->paginate($perPage);

        if ($list->isEmpty()) return [];

        $list = $list->toArray();
        $page = request()->input('page', 1);
        foreach ($list['data'] as $key=>&$val) { //下面格式化数据，按照业务需求返回数据
            $archiveManageVolume    = ArchiveManageVolume::query()->where('part_company_id', $val['id'])->first();
            $val['page1_file']      = $archiveManageVolume ? $archiveManageVolume->file_url : '';
            $val['number']          = ($page - 1) * $perPage + $key + 1;
            $val['type_text']       = PartCompany::TYPE[$val['type']];
            $val['is_can_operate']  = BookTitleService::isAllowOperate($val['id']); // 1-用户可操作案卷和卷内，0-不可以
            $val['can_match_units'] = [];
            if ($val['type'] == 2) { //如果是监理单位，获取能匹配的施工单位
                $val['can_match_units'] = $this->constructUnits($projectId, $val['id']);
            }
            if ($val['match_units']) { //如果匹配了施工单位
                $val['match_units'] = PartCompany::query()->whereIn('id', to_array($val['match_units']))->select('id', 'title')->get()->toArray();
            }
            $val['created_at'] = date('Y/m/d', strtotime($val['created_at']));
        }
        $preRefreshTime = CommonService::getFreshTime($projectId);
        $list['pre_refresh_time'] = $preRefreshTime;

        return $this->removeNoUsedPageParams($list);
    }

    /**
     * 刷新数据
     *
     * @author: lxk
     * @date: 2024/5/10 13:56
     */
    public function refreshData($projectId) : bool
    {
        $partCompanyIds = $this->getPartCompanyIds($projectId);
        foreach ($partCompanyIds as $partCompanyId) {
            $where = [
                'part_company_id' => $partCompanyId,
                'project_id'      => $projectId,
                'type'            => 1,
            ];
            RefreshLog::query()->updateOrCreate($where, [
                'total_count'      => DB::raw('total_count + 1'),
                'user_id'          => user_id(),
                'pre_refresh_time' => date('Y-m-d H:i'),
            ]);
            RefreshLog::query()->where($where)->increment('total_count');
            self::updatePaperCount($partCompanyId);
            self::updatePhotoCount($partCompanyId);
        }

        redis()->del('HomeStatistic:'.$projectId); //手动更新的话，清空该项目首页统计缓存
        redis()->del('HomeMajorCodeArchives:'.$projectId); //手动更新的话，清空该项目首页统计缓存

        return true;
    }

    /**
     * 获取用户能看到的参建单位ids
     *
     * @param $projectId
     * @return array
     * @author: lxk
     * @date: 2024/5/27 10:02
     */
    public function getPartCompanyIds($projectId) : array
    {
        $thisQuery = PartCompany::query()->where('project_id', $projectId);
        if (!is_super_admin() && !CommonService::adminLevel() ) {
            $partCompanyUser = ProjectService::partCompanyUser($projectId); //用户在项目中属于哪种参见单位类型
            if(!$partCompanyUser) return [];
            if ($partCompanyUser['type'] == 2) { //监理 可以看自己所在的监理单位和匹配的施工单位
                $partCompanyId = $partCompanyUser['part_company_id'];
                $matchUnits = PartCompany::query()->where('id', $partCompanyId)->value('match_units');
                $matchUnits = to_array($matchUnits);
                foreach ($partCompanyUser['ids'] as $partComId) {
                    array_push($matchUnits, $partComId); //自己+自己能看的施工单位ids
                }
                $thisQuery->whereIn('id', $matchUnits);
            } elseif ($partCompanyUser['type'] == 3) { //施工单位只看到自己
                $thisQuery->where('id', $partCompanyUser['part_company_id']);
            }
        }

        return $thisQuery->orderBy('id')->pluck('id')->toArray();
    }

    /**
     * 更新纸质版案卷相关数量
     */
    public static function updatePaperCount($partCompanyId)
    {
        $bookTitleCount     = 0;
        $catalogCount       = 0;
        $pageNumCount       = 0;
        $blueprintCount     = 0; //蓝图卷数
        $blueprintPageCount = 0; //蓝图张数
        $pdfCount           = 0; //PDF件数
        $pdfPageCount       = 0; //PDF张数
        $pdfDiskCount       = 0;
        /**
         * 下面获取案卷卷数、总页码、总蓝图
         */
        $baseBtTable = "book_titles_{$partCompanyId}";
        $tables = CommonService::getSubTables($baseBtTable); //获取当前参建单位下的案卷全部的分表
        foreach ($tables as $table) {
            $idInfo             = CommonService::getTableParams($table);
            $partCompanyId      = $idInfo['id1'];
            $projectClassifyId  = $idInfo['id2'];
            $count1             = DB::table($table)->whereNull('deleted_at')->count('id'); //案卷卷数
            $count2             = DB::table("book_catalogs_{$partCompanyId}_{$projectClassifyId}")->whereNull('deleted_at')->count('id'); //卷内数
            $count3             = DB::table($table)->whereNull('deleted_at')->sum('page_num'); //页码总数
            $count4             = DB::table($table)->whereNull('deleted_at')->where('blueprint', '>', 0)->count('id');
            $count5             = DB::table($table)->whereNull('deleted_at')->sum('blueprint');
            $bookTitleCount     += $count1;
            $catalogCount       += $count2;
            $pageNumCount       += $count3;
            $blueprintCount     += $count4; //蓝图总卷数，如果哪个案卷包含蓝图
            $blueprintPageCount += $count5; //蓝图总张数
            $bookTitleIds       = CommonService::getBookTitleInstance($partCompanyId, $projectClassifyId)->pluck('id')->toArray();
            foreach ($bookTitleIds as $bookTitleId) {
                $pdfPageInfo  = BookTitleService::getPdfPageNum($partCompanyId, $projectClassifyId, $bookTitleId); //扫描件件数和页数
                $pdfCount     += $pdfPageInfo['pdf_count'];
                $pdfPageCount += $pdfPageInfo['pdf_page_count'];
            }
        }
        $basePdfTable = "book_catalog_pdfs_{$partCompanyId}"; //当前参建单位所属的PDF表
        $tables = CommonService::getSubTables($basePdfTable);
        foreach ($tables as $table) {
            $idInfo   = CommonService::getTableParams($table);
            $tableExt = "{$idInfo['id1']}_{$idInfo['id2']}";
            $fileSize = DB::table("book_titles_$tableExt as bt")
                ->leftJoin("book_catalogs_$tableExt as bc", 'bt.id', '=', 'bc.book_title_id')
                ->leftJoin("book_catalog_pdfs_$tableExt as pdf", 'bc.id', '=', 'pdf.book_catalog_id')
                ->whereNull('bt.deleted_at')
                ->whereNull('bc.deleted_at')
                ->whereNull('pdf.deleted_at')
                ->sum('pdf.file_size');
            $pdfDiskCount += $fileSize;
        }
        PartCompany::query()->where('id', $partCompanyId)->update([
            'book_title_count'     => $bookTitleCount,//案卷总数
            'catalog_count'        => $catalogCount,//卷内总数
            'page_num_count'       => $pageNumCount,//页码总数
            'blueprint_count'      => $blueprintCount,//蓝图卷数
            'blueprint_page_count' => $blueprintPageCount,//蓝图张数
            'pdf_count'            => $pdfCount, //PDF件数
            'pdf_page_count'       => $pdfPageCount,//PDF张数
            'pdf_disk_count'       => round($pdfDiskCount / 1024), //占用磁盘 KB 转化为 MB
            'need_update_statistic'=> 0, //更新过后标记
        ]);
    }

    /**
     * 更新照片案卷相关数量
     */
    public static function updatePhotoCount($partCompanyId)
    {
        $photoArchiveCount = 0;
        $photoCount        = 0;
        $photoDiskCount    = 0;
        $photoClassifyIds  = PhotoClassify::query()->where('part_company_id', $partCompanyId)->orderBy('id')->pluck('id')->toArray();
        foreach ($photoClassifyIds as $photoClassifyId) {
            $table = "photo_archives_{$partCompanyId}_{$photoClassifyId}";
            if (Schema::hasTable($table)) {
                $photoArchiveInstance = (new BaseService())->getPhotoArchiveInstance($partCompanyId, $photoClassifyId);
                $count1 = $photoArchiveInstance->count('id'); //总案卷数
                $count2 = $photoArchiveInstance->sum('page_num'); //张数
                $count3 = 0; //占用硬盘
                $photoArchiveCount += $count1;
                $photoCount        += $count2;
                $photoDiskCount    += $count3;
            }
        }
        PartCompany::query()->where('id', $partCompanyId)->update([
            'photo_archive_count' => $photoArchiveCount,
            'photo_count'         => $photoCount,
            'photo_disk_count'    => round($photoDiskCount / 1024), //占用磁盘 MB 转化为 MB
        ]);
    }

    /**
     * 获取项目的全部施工单位
     *
     * @param $projectId
     * @param $supervisorId
     * @return array
     * @author: lxk
     * @date: 2024/3/20 9:57
     */
    public function constructUnits($projectId, $supervisorId) : array
    {
        $list = PartCompany::query()
            ->where('project_id', $projectId)
            ->where('type', 3)
            ->select('id', 'title')
            ->get();

        if ($list->isEmpty()) return [];

        $list = $list->toArray();
        $matchUnits = PartCompany::query()->where('id', $supervisorId)->value('match_units');
        $matchUnits = to_array($matchUnits);
        foreach ($list as &$val) { //将监理单位已经匹配的施工单位标记
            $val['select'] = 0;
            if(in_array($val['id'], $matchUnits)){
                $val['select'] = 1;
            }
        }
        return $list;
    }

    /**
     * 给监理单位绑定施工单位
     *
     * @param int $supervisorId
     * @param string $constructIds
     * @return bool
     * @author: lxk
     * @date: 2024/3/20 9:56
     */
    public function bindConstructUnits(int $supervisorId, string $constructIds) : bool
    {
        $constructIds = to_array($constructIds);
        $partCompany  = PartCompany::query()->find($supervisorId);
        $partCompany->match_units = $constructIds;

        $result = $partCompany->save();

        CommonService::addActionLog('给监理单位绑定施工单位', "数据ID:{$supervisorId}");

        return $result;
    }

    /**
     * 获取回收站数据列表
     */
    public function getRecycles($request): array
    {
        $thisQuery = PartCompany::onlyTrashed(); //只获取软删除的数据

        if ($request->filled('keyword')) { //判断参数是否存在并且不为空
            $keyword = $request->input('keyword');
            $thisQuery->where('title', 'like', "%{$keyword}%"); //由于不同的表字段不同，所以单独拿出来
        }

        return $this->formatRecycleData($request, $thisQuery);
    }

    /**
     * 获取参见单位的分类目录信息
     *
     * @param $id
     * @return array
     * @author: lxk
     * @date: 2024/3/20 9:58
     */
    public function getProjectClassifiesInfo($id) : array
    {
        return ProjectClassify::query()->where('id', $id)->first()->toArray();
    }

    /**
     * 查找 part_companies 和 project_classifies 关联的数据
     *
     * @param $classifyId
     * @return array
     * @author: lxk
     * @date: 2024/3/20 9:58
     */
    public function getPartCompanies($classifyId) : array
    {
        $list = ProjectClassify::query()
            ->with(['partCompanies:id,title', 'creator:id,nickname'])
            ->where('classify_id', $classifyId)
            ->select('id', 'part_company_id', 'classify_id', 'title as classify_title', 'creator_id', 'part_company_type')
            ->get();

        if ($list->isEmpty()) return [];

        $list = $list->toArray();
        foreach ($list as &$val) {
            if (!$val['part_companies']) { //参见单位名
                $companies['id'] = 0;
                $companies['title'] = '未知';
                $val['part_companies'] = $companies;
            }
            if (!$val['creator']) { //责任人
                $user['id'] = 0;
                $user['nickname'] = '未知';
                $val['creator'] = $user;
            }
            if ($val['part_company_type']) {
                $val['part_company_type'] = PartCompany::TYPE[$val['part_company_type']];
            }
        }

        return $list;
    }

    /**
     * 获取参见单位用户 ids
     */
    public function users(int $part_company_id)
    {
        $partCompany = PartCompany::query()->with('users')->find($part_company_id);
        if ($partCompany) {
            return $partCompany->toArray()['users'];
        }
        return [];
    }



}
